home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
PASCAL
/
1372.ZIP
/
PIBCAT.ARC
/
PIBCATA.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-10-28
|
15KB
|
327 lines
(*----------------------------------------------------------------------*)
(* Display_Archive_Contents --- Display contents of archive file *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Archive_Contents( ArcFileName : AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_Archive_Contents *)
(* *)
(* Purpose: Displays contents of an archive (.ARC file) *)
(* *)
(* Calling sequence: *)
(* *)
(* Display_Archive_Contents( ArcFileName : AnyStr ); *)
(* *)
(* ArcFileName --- name of archive file whose contents *)
(* are to be listed. *)
(* *)
(* Calls: *)
(* *)
(* Aside from internal subroutines, these routines are required: *)
(* *)
(* Dir_Convert_Date_And_Time *)
(* --- convert DOS packed date/time to string*)
(* Open_File --- open a file *)
(* Close_File --- close a file *)
(* Entry_Matches --- Perform wildcard match *)
(* Display_Page_Titles *)
(* --- Display titles at top of page *)
(* DUPL --- Duplicate a character into a string *)
(* *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Map of Archive file entry header *)
(*----------------------------------------------------------------------*)
TYPE
FNameType = ARRAY[1..13] OF CHAR;
Archive_Entry_Type = RECORD
Marker : BYTE (* Flags beginning of entry *);
Version : BYTE (* Compression method *);
Filename : FNameType (* file and extension *);
Size : LONGINT (* Compressed size *);
Date : WORD (* Packed date *);
Time : WORD (* Packed time *);
CRC : WORD (* Cyclic Redundancy Check *);
OLength : LONGINT (* Original length *);
END;
CONST
Archive_Header_Length = 29 (* Length of an archive header entry *);
Archive_Marker = 26 (* Marks start of an archive header *);
VAR
ArcFile : FILE (* Archive file to be read *);
Archive_Entry : Archive_Entry_Type (* Header for one file in archive *);
Archive_Pos : LONGINT (* Current byte offset in archive *);
Bytes_Read : INTEGER (* # bytes read from archive file *);
Ierr : INTEGER (* Error flag *);
Do_Blank_Line : BOOLEAN (* TRUE to print blank line *);
(*----------------------------------------------------------------------*)
(* Get_Next_Archive_Entry --- Get next header entry in archive *)
(*----------------------------------------------------------------------*)
FUNCTION Get_Next_Archive_Entry( VAR ArcEntry : Archive_Entry_Type;
VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_Next_Archive_Entry *)
(* *)
(* Purpose: Gets header information for next file in archive *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_Next_Archive_Entry( VAR ArcEntry : *)
(* Archive_Entry_Type; *)
(* VAR Error : INTEGER ) : *)
(* BOOLEAN; *)
(* *)
(* ArcEntry --- Header data for next file in archive *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found, else FALSE *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* Get_Next_Archive_Entry *)
(* Assume no error to start *)
Error := 0;
(* Except first time, move to *)
(* next supposed header record in *)
(* archive. *)
IF ( Archive_Pos <> 0 ) THEN
Seek( ArcFile, Archive_Pos );
(* Read in the file header entry. *)
BlockRead( ArcFile, ArcEntry, Archive_Header_Length, Bytes_Read );
Error := 0;
(* If wrong size read, or header marker *)
(* byte is incorrect, report archive *)
(* format error. *)
IF ( ( Bytes_Read < Archive_Header_Length ) OR
( ArcEntry.Marker <> Archive_Marker ) ) THEN
Error := Format_Error
ELSE (* Header looks ok -- see if it *)
(* is the end of file marker. *)
IF ( ArcEntry.Version = 0 ) THEN
Error := End_Of_File
ELSE (* Not end of file marker -- get entry data. *)
WITH ArcEntry DO
BEGIN
(* Get position of next archive header *)
Archive_Pos := Archive_Pos + Size +
Archive_Header_Length;
(* Adjust for older archives *)
IF ( Version = 1 ) THEN
BEGIN
OLength := Size;
Version := 2;
DEC( Archive_Pos , 2 );
END;
END;
(* Report success/failure to calling *)
(* routine. *)
Get_Next_Archive_Entry := ( Error = 0 );
END (* Get_Next_Archive_Entry *);
(*----------------------------------------------------------------------*)
(* Display_Archive_Entry --- Display archive file entry info *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Archive_Entry( Archive_Entry : Archive_Entry_Type );
VAR
SDate : STRING[10];
STime : STRING[12];
I : INTEGER;
FName : AnyStr;
RLength : LONGINT;
TimeDate : LONGINT;
TimeDateW : ARRAY[1..2] OF WORD ABSOLUTE TimeDate;
BEGIN (* Display_Archive_Entry *)
WITH Archive_Entry DO
BEGIN
(* Pick up file name *)
Fname := COPY( FileName, 1, PRED( POS( #0 , FileName ) ) );
(* See if this file matches the *)
(* entry spec wildcard. Exit if *)
(* not. *)
IF Use_Entry_Spec THEN
IF ( NOT Entry_Matches( Fname ) ) THEN
EXIT;
(* Make sure room on current page *)
(* for this entry name. *)
(* If enough room, print blank *)
(* line if requested. This will *)
(* only happen for first file. *)
IF Do_Blank_Line THEN
BEGIN
IF ( Lines_Left < 2 ) THEN
Display_Page_Titles
ELSE
BEGIN
WRITELN( Output_File );
DEC( Lines_left );
END;
Do_Blank_Line := FALSE;
END
ELSE
IF ( Lines_Left < 1 ) THEN
Display_Page_Titles;
(* Add '. ' to front if we're *)
(* expanding ARCs in main listing *)
IF Expand_Libs_In THEN
Fname := '. ' + Fname;
(* Get original file size *)
RLength := Olength;
(* Get date and time of creation *)
TimeDateW[1] := Time;
TimeDateW[2] := Date;
Dir_Convert_Date_And_Time( TimeDate , SDate , STime );
(* Write out file name, length, date, time *)
WRITE( Output_File , Left_Margin_String, ' ' , FName );
FOR I := LENGTH( FName ) TO 14 DO
WRITE( Output_File , ' ' );
WRITE ( Output_File , RLength:8, ' ' );
WRITE ( Output_File , SDate, ' ' );
WRITE ( Output_File , STime );
WRITELN( Output_File );
(* Count lines left on page *)
IF Do_Printer_Format THEN
DEC( Lines_Left );
(* Increment total entry count *)
INC( Total_Entries );
(* Increment total space used *)
Total_ESpace := Total_ESpace + RLength;
END;
END (* Display_Archive_Entry *);
(*----------------------------------------------------------------------*)
BEGIN (* Display_Archive_Contents *)
(* Set left margin spacing *)
Left_Margin_String := Left_Margin_String + DUPL( ' ' , Library_Indent );
(* Set file title *)
File_Title := Left_Margin_String + ' Archive file: ' + ArcFileName;
(* Display archive file's name *)
IF Do_Printer_Format THEN
IF ( Lines_Left < 3 ) THEN
Display_Page_Titles;
(* If we're listing contents at end *)
(* of directory, print archive name. *)
(* Do_Blank_Line flags whether we *)
(* need to print blank line in entry *)
(* lister subroutine. If listing *)
(* inline, then it's true for the *)
(* first file; otherwise it's false. *)
(* This is to prevent unnecessary *)
(* blank lines in output listing *)
(* when no files are selected from *)
(* a given archive. *)
IF ( NOT Expand_Libs_In ) THEN
BEGIN
WRITELN( Output_File ) ;
WRITE ( Output_File , File_Title );
DEC( Lines_Left , 2 );
Do_Blank_Line := FALSE;
END
ELSE
Do_Blank_Line := TRUE;
(* Try opening archive file for processing *)
Open_File( ArcFileName , ArcFile, Archive_Pos, Ierr );
(* Issue error message if open fails *)
IF ( Ierr <> 0 ) THEN
BEGIN
WRITELN( Output_File ,
DUPL( ' ' , MAX( 0 , MIN( 12 , 13 - LENGTH( ArcFileName ) ) ) ),
' Can''t open archive file ',ArcFileName );
IF Do_Printer_Format THEN
BEGIN
DEC( Lines_Left );
IF ( Lines_Left < 1 ) THEN
Display_Page_Titles;
END;
EXIT;
END
ELSE IF ( NOT Expand_Libs_In ) THEN
BEGIN
WRITELN( Output_File );
WRITELN( Output_File );
(* Count lines left on page *)
IF Do_Printer_Format THEN
DEC( Lines_Left );
END;
(* Loop over entries in archive file *)
WHILE( Get_Next_Archive_Entry( Archive_Entry , Ierr ) ) DO
Display_Archive_Entry( Archive_Entry );
(* Print blank line after last entry *)
(* in archive, if we're expanding *)
(* archives right after listing them, *)
(* but only if archive had any entries *)
(* listed. *)
IF ( Expand_Libs_In AND ( NOT Do_Blank_Line ) ) THEN
BEGIN
WRITELN( Output_File );
IF Do_Printer_Format THEN
DEC( Lines_Left );
END;
(* Close archive file *)
Close_File( ArcFile );
(* Restore previous left margin spacing *)
Left_Margin_String := DUPL( ' ' , Left_Margin );
(* No file title *)
File_Title := '';
END (* Display_Archive_Contents *);